#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "lc_array.h"
#include "pac_level.h"
#include "pac_object.h"
#include "pac_ghost.h"
#include "pac_logger.h"

void extractMap(PacLevel* aLevel, FILE * aLevelFile) {
    pac_log(LOG_DEBUG, "extractMap\n");
    // Tailles de la map.
    int sizeX, sizeY;

    // Lecture des deux premier chiffre du fichier (taille de la map)
    fscanf(aLevelFile, "%d %d", &sizeX, &sizeY);
    printf("Taille de la map : (%d,%d)\n", sizeX, sizeY);

    // Assignation des paramètres concernant les vitesses
    int pacmanSpeed, ghostNormalSpeed, ghostVulnerableSpeed, ghostIntelligence, powerballDuration;
    // Lecture des quatres chiffres suivant du fichier (vitesses)
    fscanf(aLevelFile, "%d %d %d %d %d", &pacmanSpeed, &ghostNormalSpeed, &ghostVulnerableSpeed, &ghostIntelligence, &powerballDuration);
    aLevel->pacman_speed = pacmanSpeed;
    aLevel->ghost_normal_speed = ghostNormalSpeed;
    aLevel->ghost_vulnerable_speed = ghostVulnerableSpeed;
    aLevel->powerball_duration = powerballDuration;
    aLevel->ghostIntelligence = ghostIntelligence;

    printf("Vitesse de PacMan : %d\n", pacmanSpeed);
    printf("Vitesse des fantômes en chasse : %d\n", ghostNormalSpeed);
    printf("Vitesse des fantômes vulnérables : %d\n", ghostVulnerableSpeed);
    printf("Intelligence des fantômes : %d\n", ghostIntelligence);
    printf("Durée des pouvoirs : %d\n", powerballDuration);
    printf("Contenu : \n");

    // Initialisation des structures de stockage
    LCarray* mapMatrix = lcArrayCreate();
    LCarray* pacBallsMatrix = lcArrayCreate();
    LCarray* ghostsList = lcArrayCreate();

    int x, y, currentvalue;

    // Itération sur toute les lignes de la map à charger
    for (y = 0; y < sizeY; y++) {

        // Ligne de map courrante
        LCarray* currentMapLine = lcArrayCreate();

        // Ligne de PacBalls courante
        LCarray* currentPacBallsLine = lcArrayCreate();

        // Itération sur toute les valeurs de la map à charger
        for (x = 0; x < sizeX; x++) {

            // Récupération de la valeur courante.
            fscanf(aLevelFile, " %d", &currentvalue);

            // Ecriture de la valeur récupérée
            printf("%i ", currentvalue);

            // Traitement de la valeur à la ligne courante.
            switch (currentvalue) {
                case PAC_GUM_CODE:
                    lcArrayAdd(currentMapLine, PAC_GUM_CODE);
                    lcArrayAdd(currentPacBallsLine, PAC_GUM_CODE);
                    aLevel->initialPacBallCount++;
                    break;

                case BLOCK_CODE:
                    lcArrayAdd(currentMapLine, BLOCK_CODE);
                    lcArrayAdd(currentPacBallsLine, EMPTY_CODE);
                    break;

                case POWER_BALL_CODE:
                    lcArrayAdd(currentMapLine, POWER_BALL_CODE);
                    lcArrayAdd(currentPacBallsLine, POWER_BALL_CODE);
                    aLevel->initialPacBallCount++;
                    break;

                case PACMAN_START:
                    lcArrayAdd(currentMapLine, EMPTY_CODE);
                    lcArrayAdd(currentPacBallsLine, EMPTY_CODE);

                    aLevel->pacMan = pacObjectCreate(x, y);
                    break;

                case FENCE_CODE:
                    lcArrayAdd(currentMapLine, FENCE_CODE);
                    lcArrayAdd(currentPacBallsLine, EMPTY_CODE);
                    break;

                case GHOST_CODE:
                    lcArrayAdd(currentMapLine, EMPTY_CODE);
                    lcArrayAdd(currentPacBallsLine, EMPTY_CODE);

                    // Création puis ajout d'un fantome
                    boolean isIntelligent = getRandomIntUnder(2);
                    PacGhost* newGhost = pacGhostCreate(x, y, isIntelligent);
                    lcArrayAdd(ghostsList, newGhost);
                    break;

                default:
                    // Si le nombre est négatif
                    if (currentvalue < 0) {
                        // Ajout d'un téléporteur
                        lcArrayAdd(currentMapLine, currentvalue);
                    } else {
                        // Sinon, ajout d'un mur
                        lcArrayAdd(currentMapLine, BLOCK_CODE);

                    }
                    // Dans tous les cas, pas de PacBall sur la case
                    lcArrayAdd(currentPacBallsLine, EMPTY_CODE);
            }
        }

        printf("\n");

        // Ajout de la ligne courrante à la matrice de Map
        lcArrayAdd(mapMatrix, currentMapLine);

        // Ajout de la ligne courrante à la matrice de PacBalls
        lcArrayAdd(pacBallsMatrix, currentPacBallsLine);
    }


    // Assignation des structures extraites
    aLevel->map = mapMatrix;
    aLevel->initialPacBalls = pacBallsMatrix;
    aLevel->ghosts = ghostsList;
}

int loadPacMap(PacLevel* aLevel, char * aFileName) {
    pac_log(LOG_DEBUG, "loadPacMap\n");
    FILE* levelFile = NULL;

    printf("File : '%s'\n", aFileName);

    levelFile = fopen(aFileName, "r+");

    if (levelFile != NULL) {
        extractMap(aLevel, levelFile);
        fclose(levelFile);
    } else {
        printf("Impossible d'ouvrir le fichier '%s'\n", aFileName);
        return -1;
    }
    return 0;
}
